#include "ImageDenoise.h"
#include "InterpolateLinear.h"


ImageDenoise::ImageDenoise () : g_rgbImageSmoothed (NULL), _rImage (NULL),
		_gImage (NULL), _bImage (NULL)
{
}


ImageDenoise::~ImageDenoise ()
{
	if (g_rgbImageSmoothed) {
		cvReleaseImage (&g_rgbImageSmoothed);
		cvReleaseImage (&_rImage);
		cvReleaseImage (&_gImage);
		cvReleaseImage (&_bImage);
	}
}

void ImageDenoise::process (IplImage *image)
{
	if (!image)
		return;
	if (!g_rgbImageSmoothed) {
		 g_rgbImageSmoothed = cvCreateImage (cvGetSize (image), 8, 3);
		 _rImage = cvCreateImage (cvGetSize (image), 8, 1);
		 _gImage = cvCreateImage (cvGetSize (image), 8, 1);
		 _bImage = cvCreateImage (cvGetSize (image), 8, 1);
	}

// For Debug
// 	for (int v = 0; v < image->height; ++v) {
// 		for (int u = 0; u < image->width; ++u) {
// 			CV_IMAGE_ELEM (_rImage, unsigned char, v, u) =
// 				CV_IMAGE_ELEM (image, unsigned char, v, u * 3 + 2);
// 			CV_IMAGE_ELEM (_gImage, unsigned char, v, u) =
// 				CV_IMAGE_ELEM (image, unsigned char, v, u * 3 + 1);
// 			CV_IMAGE_ELEM (_bImage, unsigned char, v, u) =
// 				CV_IMAGE_ELEM (image, unsigned char, v, u * 3 + 0);
// 		}
// 	}
// 	cvShowImage ("Orig Image", image);
//  	cvShowImage ("Orig R Image", _rImage);
// 	cvShowImage ("Orig G Image", _gImage);
//  	cvShowImage ("Orig B Image", _bImage);

	InterpolateLinear interpolate;

	// R
	for (int v = 0; v < image->height; ++v) {
		for (int u = 0; u < image->width; ++u) {
			float offset = -0.7f;
			if ((v % 2)) offset = -1.2f;
			float uSrc = (float)u + offset;
			if (uSrc < 0) uSrc = 0;
			else if (uSrc >= image->width) uSrc = image->width - 1;
			CV_IMAGE_ELEM (g_rgbImageSmoothed, unsigned char, v, u * 3 + 2) =
					interpolate.interpolate (image, cvPoint2D32f (uSrc, v)).val[2];
// 					CV_IMAGE_ELEM (image, unsigned char, v,
// 					uSrc * 3 + 2);
		}
	}
	// G
	for (int v = 0; v < image->height; ++v) {
		for (int u = 0; u < image->width; ++u) {
			float offset = 0.0;
			if (v % 2) offset = -1.0;
			float uSrc = (float)u + offset;
			if (uSrc < 0) uSrc = 0;
			else if (uSrc >= image->width) uSrc = image->width - 1;
			CV_IMAGE_ELEM (g_rgbImageSmoothed, unsigned char, v, u * 3 + 1) =
					interpolate.interpolate (image, cvPoint2D32f (uSrc, v)).val[1];
// 					CV_IMAGE_ELEM (image, unsigned char, v,
// 					uSrc * 3 + 1);
		}
	}
	// B
	for (int v = 0; v < image->height; ++v) {
		for (int u = 0; u < image->width; ++u) {
			float offset = 1.0f;
			if (u % 2) offset = 0.4f;
			float vSrc = (float)v + offset;
			if (vSrc < 0) vSrc = 0;
			else if (vSrc >= image->height) vSrc = image->height - 1;
 			CV_IMAGE_ELEM (g_rgbImageSmoothed, unsigned char, v, u * 3 + 0) =
					interpolate.interpolate (image, cvPoint2D32f (u, vSrc)).val[0];
// 					CV_IMAGE_ELEM (image, unsigned char, vSrc,
// 					u * 3 + 0);
		}
	}
// 	cvSmooth (g_rgbImageSmoothed, image, CV_MEDIAN);
	cvCopy (g_rgbImageSmoothed, image);

// For Debug
// 	for (int v = 0; v < image->height; ++v) {
// 		for (int u = 0; u < image->width; ++u) {
// 			CV_IMAGE_ELEM (_rImage, unsigned char, v, u) =
// 				CV_IMAGE_ELEM (image, unsigned char, v, u * 3 + 2);
// 			CV_IMAGE_ELEM (_gImage, unsigned char, v, u) =
// 				CV_IMAGE_ELEM (image, unsigned char, v, u * 3 + 1);
// 			CV_IMAGE_ELEM (_bImage, unsigned char, v, u) =
// 				CV_IMAGE_ELEM (image, unsigned char, v, u * 3 + 0);
// 		}
// 	}
// 	cvShowImage ("Image", image);
//  	cvShowImage ("R Image", _rImage);
// 	cvShowImage ("G Image", _gImage);
//  	cvShowImage ("B Image", _bImage);
}
